﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BM.Core.Data;
using NHibernate;
using NHibernate.Criterion;
using System.Collections;
namespace BM.Data.NHB
{
    public partial class NHBRepository<T> : ITransactionable, IRepository<T> where T : BM.Core.BaseEntity
    {

        public NHBRepository(ISession Session)
        {
            this.Session = Session;
        }

        private ISession session;
        private ITransaction trans;

        public ITransaction Transaction
        {
            get { return trans; }
            private set { trans = value; }
        }
        public ISession Session
        {
            get { return session; }
            private set { session = value; }
        }

        public T GetById(object id)
        {
            return Session.Get<T>(id);
        }

        public void Insert(T entity)
        {
            Session.Save(entity);
            Session.Flush();
        }

        public void Update(T entity)
        {
            Session.Update(entity);
            Session.Flush();
        }

        public void Delete(T entity)
        {
            Session.Delete(entity);
            Session.Flush();
        }

        public IList<T> GetAll()
        {
            return Session.CreateCriteria<T>().List<T>();
        }

        public void Begion()
        {
            Transaction = Session.BeginTransaction();
        }

        public void Rollback()
        {
            if (Transaction == null)
            {
                return;
            }
            Transaction.Rollback();
        }

        public void Commit()
        {
            if (Transaction == null)
            {
                return;
            }
            Transaction.Commit();
        }

        #region Delete



        /// <summary>
        /// 根据hql语句删除
        /// <example>
        /// hql="from 类名 where 属性名=值"
        /// </example>
        /// </summary>
        /// <param name="hql">hql语句</param>
        public void DeleteByQuery(string hql)
        {
            Session.Delete(hql);
            Session.Flush();
        }

        /// <summary>
        /// 根据Query进行删除
        /// <example>
        /// hql="delete from 类名 where 属性名=:参数名";
        /// </example>
        /// </summary>
        /// <param name="hql">hql语句</param>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数值</param>
        public void DeleteByQuery(string hql, string name, object value)
        {
            DeleteByQuery(hql, new string[] { name }, new object[] { value });
        }

        /// <summary>
        /// 根据Query进行删除
        /// <example>
        /// hql="delete from 类名 where 属性名=:参数名";
        /// </example>
        /// </summary>
        /// <param name="hql">hql语句</param>
        /// <param name="names">参数名称数组</param>
        /// <param name="values">参数值数组</param>
        public void DeleteByQuery(string hql, string[] names, object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            query.ExecuteUpdate();
            Session.Flush();
        }

        /// <summary>
        /// 根据Query进行删除
        /// <example>
        /// hql="delete from 类名 where 属性名=? and 属性名=？";
        /// </example>
        /// </summary>
        /// <param name="hql">hql语句</param>
        /// <param name="values">参数值数组</param>
        public void DeleteByQuery(string hql, object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            query.ExecuteUpdate();
            Session.Flush();
        }

        #endregion

        #region Count

        public int Count()
        {
            ICriteria criteria = Session.CreateCriteria<T>();
            return Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
        }

        public int Count(ICriterion expression)
        {
            ICriteria criteria = Session.CreateCriteria<T>();
            if (expression != null)
            {
                criteria.Add(expression);
            }
            return Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
        }

        #endregion

        #region Scalar

        public object Scalar(string hql)
        {
            return Session.CreateQuery(hql).UniqueResult();
        }

        public object Scalar(string hql, params object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.UniqueResult();
        }

        public object Scalar(string hql, string name, object value)
        {
            return Scalar(hql, new string[] { name }, new object[] { value });
        }

        public object Scalar(string hql, string[] names, object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.UniqueResult();
        }


        public object Scalar(string hql, Action<IQuery> action)
        {
            IQuery query = Session.CreateQuery(hql);
            action(query);
            return query.UniqueResult();
        }

        #endregion

        #region ScalarBySQL

        public object ScalarBySQL(string sql)
        {
            return Session.CreateSQLQuery(sql).UniqueResult();
        }

        public object ScalarBySQL(string sql, params object[] values)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.UniqueResult();
        }

        public object ScalarBySQL(string sql, string name, object value)
        {
            return ScalarBySQL(sql, new string[] { name }, new object[] { value });
        }

        public object ScalarBySQL(string sql, string[] names, object[] values)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.UniqueResult();
        }

        public object ScalarBySQL(string sql, Action<ISQLQuery> action)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            action(query);
            return query.UniqueResult();
        }

        #endregion

        #region Query



        public IList<T> Query(Action<ICriteria> action)
        {
            ICriteria criteria = Session.CreateCriteria<T>();
            action(criteria);
            return criteria.List<T>();
        }

        public IList<T> Query(ICriterion expression)
        {
            return Query(expression, null);
        }

        public IList<T> Query(ICriterion expression, Action<ICriteria> action)
        {
            ICriteria criteria = Session.CreateCriteria<T>();
            if (expression != null)
            {
                criteria.Add(expression);
            }
            if (action != null)
            {
                action(criteria);
            }
            return criteria.List<T>();
        }

        public IList<T> Query(string hql)
        {
            return Session.CreateQuery(hql).List<T>();
        }

        public IList<T> Query(string hql, params object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.List<T>();
        }

        public IList<T> Query(string hql, string name, object value)
        {
            return Query(hql, new string[] { name }, new object[] { value });
        }

        public IList<T> Query(string hql, string[] names, object[] values)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.List<T>();
        }

        public IList<T> Query(string hql, Action<IQuery> action)
        {
            IQuery query = Session.CreateQuery(hql);
            action(query);
            return query.List<T>();
        }

        #endregion

        #region Page Query

        public IList<T> Query(int pageIndex, int pageSize, out int recordCount)
        {
            return Query(null, null, pageIndex, pageSize, out recordCount);
        }

        public IList<T> Query(ICriterion expression, int pageIndex, int pageSize, out int recordCount)
        {
            return Query(expression, null, pageIndex, pageSize, out recordCount);
        }

        public IList<T> Query(ICriterion expression, Order[] order,
            int pageIndex, int pageSize, out int recordCount)
        {
            IList<T> list = new List<T>();
            recordCount = 0;
            ICriteria query = Session.CreateCriteria<T>();
            if (expression != null)
            {
                query.Add(expression);
            }
            ICriteria queryPage = CriteriaTransformer.Clone(query);
            //获取记录总数
            recordCount = Convert.ToInt32(query.SetProjection(Projections.RowCount()).UniqueResult());

            //设置排序
            if (order != null)
            {
                foreach (Order o in order)
                {
                    queryPage.AddOrder(o);
                }
            }
            queryPage.SetFirstResult((pageIndex - 1) * pageSize);
            queryPage.SetMaxResults(pageSize);
            list = queryPage.List<T>();

            return list;
        }

        public IList<T> Query(string hql, object[] values, int pageIndex, int pageSize)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List<T>();
        }

        public IList<T> Query(string hql, string name, object value, int pageIndex, int pageSize)
        {
            return Query(hql, new string[] { name }, new object[] { value }, pageIndex, pageSize);
        }

        public IList<T> Query(string hql, string[] names, object[] values, int pageIndex, int pageSize)
        {
            IQuery query = Session.CreateQuery(hql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List<T>();
        }

        public IList<T> Query(string hql, int pageIndex, int pageSize)
        {
            IQuery query = Session.CreateQuery(hql);
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List<T>();
        }

        #endregion

        #region SQL Query

        public IList QueryBySQL(string sql)
        {
            return Session.CreateSQLQuery(sql).List();
        }

        public IList QueryBySQL(string sql, params object[] values)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.List();
        }

        public IList QueryBySQL(string sql, string name, object[] value)
        {
            return QueryBySQL(sql, new string[] { name }, new object[] { value });
        }

        public IList QueryBySQL(string sql, string[] names, object[] values)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.List();
        }

        public IList QueryBySQL(string sql, Action<ISQLQuery> action)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            action(query);
            return query.List();
        }

        #endregion

        #region Page SQL Query

        public IList QueryBySQL(string sql, object[] values, int pageIndex, int pageSize)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < values.Length; i++)
            {
                query.SetParameter(i, values[i]);
            }
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List();
        }

        public IList QueryBySQL(string sql, string name, object value, int pageIndex, int pageSize)
        {
            return QueryBySQL(sql, new string[] { name }, new object[] { value }, pageIndex, pageSize);
        }

        public IList QueryBySQL(string sql, string[] names, object[] values, int pageIndex, int pageSize)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            for (int i = 0; i < names.Length; i++)
            {
                query.SetParameter(names[i], values[i]);
            }
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List();
        }

        public IList QueryBySQL(string sql, int pageIndex, int pageSize)
        {
            ISQLQuery query = Session.CreateSQLQuery(sql);
            return query.SetFirstResult((pageIndex - 1) * pageSize).SetMaxResults(pageSize).List();
        }

        #endregion

    }
}
